package cn.maihe.elg.operation.centers.follow.handler.service;

import cn.maihe.elg.operation.centers.follow.channel.dto.FollowBaseRespDTO;
import cn.maihe.elg.operation.centers.follow.channel.dto.GuarantorClaimSettleNoticeReqDTO;
import cn.maihe.elg.operation.centers.follow.channel.service.GuarantorClaimSettleNoticeChannelService;
import cn.maihe.elg.operation.centers.follow.handler.FollowBaseResp;
import cn.maihe.elg.operation.centers.follow.handler.FollowCenterTradeService;
import cn.maihe.elg.operation.centers.follow.handler.dto.GuaranteeClaimSettlementReqDTO;
import cn.maihe.elg.operation.centers.supports.CenterTradeContext;
import cn.maihe.elg.operation.centers.supports.annotation.CenterTradeService;
import cn.maihe.elg.operation.model.dto.BaseResp;
import cn.maihe.elg.operation.model.enums.*;
import cn.maihe.elg.operation.repository.entity.AcceptOrderInfoDO;
import cn.maihe.elg.operation.repository.entity.RefundOrderInfoDO;
import cn.maihe.elg.operation.service.order.AcceptOrderInfoService;
import cn.maihe.elg.operation.service.order.ApplyOrderInfoService;
import cn.maihe.elg.operation.service.order.NoticeRetryInfoService;
import cn.maihe.elg.operation.service.order.RefundOrderInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * @Description
 * @Author caixh
 * @Date 2021/9/17.
 */
@CenterTradeService(
        provider = CenterProviderEnum.FOLLOW,
        centerNo = CenterNoEnum.SANMING,
        tradeType = TradeType.guarantee_claim_settlement,
        reqClass = GuaranteeClaimSettlementReqDTO.class,
        respClass = FollowBaseResp.class
)
@Slf4j
public class FollowGuaranteeClaimSettlementService extends FollowCenterTradeService<GuaranteeClaimSettlementReqDTO, BaseResp> {

    @Resource
    ApplyOrderInfoService applyOrderInfoService;
    @Resource
    AcceptOrderInfoService acceptOrderInfoService;
    @Resource
    RefundOrderInfoService refundOrderInfoService;
    @Resource
    GuarantorClaimSettleNoticeChannelService claimSettleNoticeChannelService;
    @Resource
    NoticeRetryInfoService noticeRetryInfoService;

    /**
     * 具体业务处理
     *
     * @param context
     */
    @Override
    public BaseResp processService(CenterTradeContext<GuaranteeClaimSettlementReqDTO, BaseResp> context) {
        GuaranteeClaimSettlementReqDTO req = context.getReq();
        Assert.notNull(req.getData(), () -> "理赔业务数据不能为空");
        Assert.hasText(req.getData().getPolicyNo(), "保函编号不能为空");
        Long centerId = context.getCenterId();
        Long orgId = context.getOrgId();
        String guaranteeNo = req.getData().getPolicyNo();

        //查询申请保函记录及状态是否已出函状态
        AcceptOrderInfoDO acceptOrderInfo = acceptOrderInfoService.getByGuaranteeNo(centerId, orgId, guaranteeNo);
//        ApplyOrderInfoDO applyOrderInfo = applyOrderInfoService.getByGuaranteeNo(guaranteeNo);
        Assert.notNull(acceptOrderInfo, "查无此保函编号申请记录");
        Assert.isTrue(AcceptOrderStatus.HAS_OUT_GUARANTEE.getStatus() == acceptOrderInfo.getStatus(), "此保函非出函状态不能申请理赔");

        AcceptOrderInfoDO updateOrderInfo = AcceptOrderInfoDO.builder().id(acceptOrderInfo.getId())
                .claimsStatus(ClaimsStatus.PROCESSING.getStatus()).claimsRemark(req.getData().getReason()).build();
        acceptOrderInfoService.updateById(updateOrderInfo);

        RefundOrderInfoDO refundOrderInfoDO = refundOrderInfoService.getByGuaranteeNo(guaranteeNo);
        if (refundOrderInfoDO != null) {
            Integer refundStatus = refundOrderInfoDO.getStatus();
            if (refundStatus != null) {
                RefundOrderStatus enums = RefundOrderStatus.resolve(refundStatus.intValue());
                throw new RuntimeException("该保函理赔已申请，当前处理状态" + enums);
            }
        }

        refundOrderInfoService.insertByClaimSettlement(acceptOrderInfo);


//        asyncClaimSettleNotice(acceptOrderInfo);

        return null;
    }

    private void asyncClaimSettleNotice(AcceptOrderInfoDO infoDO) {
        CompletableFuture.runAsync(() -> {

            try {
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                throw new RuntimeException("睡眠中断异常");
            }

            GuarantorClaimSettleNoticeReqDTO reqDTO = new GuarantorClaimSettleNoticeReqDTO();
            reqDTO.setPolicyNo(infoDO.getGuaranteeNo());
            reqDTO.setStatus("2");
            reqDTO.setMsg("理赔完成");
            FollowBaseRespDTO respDTO = claimSettleNoticeChannelService.doRequest(reqDTO);
            Assert.notNull(respDTO, "响应报文不能为空");
            if (!"200".equals(respDTO.getCode())) {

                noticeRetryInfoService.saveOrUpdateNoticeRetryInfo(NoticeTypeEnum.claims_apply_result,
                        infoDO.getCenterId(), infoDO.getOrgId(),
                        infoDO.getAcceptOrderNo(), reqDTO, null, respDTO
                );
                throw new RuntimeException("响应码非成功[" + respDTO.getCode() + ":" + respDTO.getMsg() + "]");
            }
            log.info("保函编号[{}] >> 理赔结果回调通知成功", infoDO.getGuaranteeNo());
        }).whenCompleteAsync((r, e) -> {
            if (e != null) {
                log.error("保函编号[{}] >> 理赔结果回调通知异常：{}", infoDO.getGuaranteeNo(), e.getMessage(), e);
            }
        });

    }
}
